package be.ac.ua.pats.thesisrobotica.robot.communication;

//~--- non-JDK imports --------------------------------------------------------

import be.ac.ua.pats.thesisrobotica.robot.exceptions.InitializationException;
import be.ac.ua.pats.thesisrobotica.robot.exceptions.InvalidConnectionException;
import be.ac.ua.pats.thesisrobotica.robot.exceptions.RobotInitializationException;
import be.ac.ua.pats.thesisrobotica.robot.exceptions.SensorNotFoundException;
import be.ac.ua.pats.thesisrobotica.robot.main.Robot;
import be.ac.ua.pats.thesisrobotica.robot.parser.MessageParser;

import lejos.nxt.comm.*;

//~--- JDK imports ------------------------------------------------------------

import java.io.*;

/**
 *
 * @author Admin
 */
public class BluetoothConnection extends BTConnection implements Connection {
    boolean          connected = false;
    BTConnection     connection;
    DataInputStream  iStream;
    DataOutputStream oStream;
    protected int    written;
    MessageParser parser;

    public BluetoothConnection(Robot robot) {
        
       super(BluetoothConnection.PACKET);

        RConsole.print("Trying to connect");

        connection = Bluetooth.waitForConnection();

        RConsole.print("Connected");

        connected = true;
        oStream   = new DataOutputStream(connection.openOutputStream());
        iStream   = new DataInputStream(connection.openInputStream());

        parser = new MessageParser(robot);


    }

    public boolean isConnected() {
        return connected;
    }

    /**
     * Sends an integer over the bluetooth connection
     *
     * @param i The integer to be sent
     */
    private void send(int i) {
        try {
            RConsole.println("Sending int: " + i);
            oStream.writeInt(i);
            oStream.flush();
        } catch (IOException ex) {
            RConsole.println("IOException in BluetoothConnection:send with parameter " + i);
        }
    }

    /**
     * Sends a string over the bluetooth connection
     *
     * @param s The string to be sent
     */
    public void send(String s) {
        try {
            if(connected) {
                char[] charArray = s.toCharArray();

                // First send the length of the char array
                this.send(charArray.length);

                int i = 0;

                for (char c : charArray) {
                    oStream.writeChar(c);
                    /**
                    // flush after every 30. char
                    if (i % 4 == 0) {
                        oStream.flush();
                    }

                    i++;
                     * */
                }

                // Flush all
                RConsole.println("Sending string: "+s);
                oStream.flush();
            } else {
                throw new InvalidConnectionException(this.getAddress());
            }
        } catch (IOException e) {
            RConsole.println("IOException in BluetoothcConnection:send with parameter " + s);
        } catch (Exception e) {
            RConsole.println("Exception in BluetoothConnection:send with parameter " + s);
        }
    }

    public void disconnect() {
        try {
            this.send("D");
            connected = false;

            connection.closeStream();
            connection.close();
        } catch (Exception e) {
            RConsole.println("Exception in BluetoothConnection:disconnect:disconnect with parameter " + e);
        }
    }

    public void run() {
        try {
            StringBuilder resString = new StringBuilder();

            RConsole.println("Starting up connection");

            while (connected) {
                int  stringLength = iStream.readInt();
                char n;

                for (int i = 0; i < stringLength; i++) {
                    n = iStream.readChar();

                    resString.append(n);
                }

                RConsole.println("Received: "+resString.toString());
                try {
                    try {
                        parser.parse(resString.toString());
                    } catch (RobotInitializationException ex) {
                        RConsole.println("RobotInitializationException");
                    }
                } catch (InitializationException ex) {
                   
                }

                resString = new StringBuilder();
            }
        } catch (InvalidConnectionException ex) {
            RConsole.println("InvalidConnectionException in BluetoothConnection:run");
        } catch (SensorNotFoundException ex) {
            RConsole.println("SensorNotFoundException in BluetoothConnection:run: "+ex.getMessage());
        } catch (InterruptedException ex) {
            RConsole.println("InterruptedException in BluetoothConnection:run");
        } catch (IOException ex) {
            RConsole.println("Exception in BluetoothConnection:run");
        }
    }
}
